package com.yami.shop.service;

import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RecommendationService {
    private final RedisTemplate<String, String> redisTemplate;

    /**
     * 基于用户协同过滤的实时推荐方法
     * @param userId 目标用户的唯一标识符（字符串格式）
     * @param topN 需要返回的推荐商品数量
     * @return 推荐商品ID列表（按Long类型转换后的结果）
     */
    public List<Long> recommendItems(String userId, int topN) {
        // 用户行为数据键构造
        String userKey = "user:" + userId + ":items";
        // 用户相似度关系键构造
        String similarityKey = "similarity:user:" + userId;

        // 获取用户历史浏览记录（空集合防御处理）
        Set<String> viewedItems = redisTemplate.opsForSet().members(userKey);
        if (viewedItems == null) {
            viewedItems = Collections.emptySet();
        }

        // 获取TopN相似用户集合（使用ZSET逆序获取高分值用户）
        Set<String> similarUsers = redisTemplate.opsForZSet().reverseRange(similarityKey, 0, topN - 1);
        if (similarUsers == null) {
            similarUsers = Collections.emptySet();
        }

        // 聚合相似用户行为数据（多用户商品合并）
        Set<String> recommendedItems = new HashSet<>();
        similarUsers.forEach(similarUser -> {
            String similarUserKey = "user:" + similarUser + ":items";
            Set<String> items = redisTemplate.opsForSet().members(similarUserKey);
            if (items != null) {
                recommendedItems.addAll(items);
            }
        });

        // 过滤去重逻辑（排除已浏览商品 + 类型转换）
        recommendedItems.removeAll(viewedItems);
        return recommendedItems.stream()
                .map(Long::parseLong)
                .collect(Collectors.toList());
    }

    /**
     * 基于物品协同过滤的推荐方法（备选方案）
     * @param userId 目标用户的唯一标识符（Long类型）
     * @param topN 需要返回的推荐商品数量
     * @return 推荐商品ID列表（按Long类型转换后的结果）
     */
    public List<Long> recommendItemsByItemCF(Long userId, int topN) {
        // 用户历史行为数据获取
        String userKey = "user:" + userId + ":items";
        Set<String> viewedItems = redisTemplate.opsForSet().members(userKey);
        if (viewedItems == null) {
            viewedItems = Collections.emptySet();
        }

        // 物品相似度扩展推荐（基于用户浏览历史扩展相似物品）
        Set<String> similarItems = new HashSet<>();
        viewedItems.forEach(itemId -> {
            String itemSimilarityKey = "similarity:item:" + itemId;
            Set<String> topSimilarItems = redisTemplate.opsForZSet().reverseRange(itemSimilarityKey, 0, topN - 1);
            if (topSimilarItems != null) {
                similarItems.addAll(topSimilarItems);
            }
        });

        // 过滤处理与结果转换
        similarItems.removeAll(viewedItems);
        return similarItems.stream()
                .map(Long::parseLong)
                .collect(Collectors.toList());
    }
}
